<template>
  <div class="wrokbench-box">
    <HeaderBox
      @set-web-socket-status="setWebSocketStatus"
      ref="headerBox"
      :userDetail="userDetail"
    />
    <div class="wrokbench-content">
      <ChatList
        :onlineCustomerList="onlineCustomerList"
        :messageList="messageList"
        @select-chat="selectChat"
        @load-scroll="loadScroll"
        @clear-store-target="clearStoreTarget"
      />
      <ChatCotent
        :messageList="messageList"
        :chatMap="chatMap"
        @customer-send-message="customerSendMessage"
        @crm-update="crmUpdate"
        ref="chatDom"
      />
      <ChatRight :chatMap="chatMap" @resh-customers="reshCustomers" ref="chatRight" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import HeaderBox from './views/header.vue'
import ChatList from './views/chatList.vue'
import ChatCotent from './views/chatCotent.vue'
import ChatRight from './views/chatRight.vue'
import { getByKey, getChatMessage, getCustomerPage } from '@/api/service/workbench/index'
import { getNowFormatDate, formatDates } from '@/utils/public'
import globalWebcookies from '@/utils/globalWebcookies'
const route = useRoute()

const listIcon = globalWebcookies.listIcon
const { status, send, close, open } = globalWebcookies.websocketObj
const data = globalWebcookies.data
import { useUserStore } from '@/store/modules/user'
const store = useUserStore()

const chatRight = ref(null)
const headerBox = ref(null)
const userDetail = ref({
  name: '',
  avator: ''
})
/*客服分页*/
const limit = ref({
  pageNo: 1,
  pageSize: 20
})
/*消息提示*/
const message = useMessage()
/*客户列表*/
const onlineCustomerList = ref({})
/*客户、客服聊天列表*/
const chatMap = ref([])
const chatDom = ref(null)
const changeSessionId = ref(null)

/*消息列表*/
const messageList = ref({})
watch(
  data,
  (newValue) => {
    if (!newValue) return
    try {
      if (newValue == 'pong') {
        return
      }
      // 2.1 解析 type 消息类型
      const jsonMessage = JSON.parse(newValue)
      const type = jsonMessage.type
      const content = JSON.parse(jsonMessage.content)
      if (!type) {
        message.error('未知的消息类型：' + newValue)
        return
      }
      // 2.2 消息类型：demo-message-receive
      if (type === 'service-chat-message-receive') {
        content.time = getNowFormatDate()
        content.type = 'you'
        // 红点
        if (changeSessionId.value) {
          content.reading = content.fromUserKey == changeSessionId.value ? false : true
        } else {
          content.reading = true
        }
        if (
          Object.keys(onlineCustomerList.value).length &&
          onlineCustomerList.value[content.fromUserKey]
        ) {
          for (const key in onlineCustomerList.value) {
            if (key == content.fromUserKey) {
              addMessage(content)
              moveKeyToFront(content.fromUserKey)
              onlineCustomerList.value[key].status = 1
              break
            }
          }
          chatDom.value.scrollDom()
        } else {
          // 新增客户
          addMyCustomer(content)
        }
      }
    } catch (e) {}
  },
  { deep: true, immediate: true }
)
/*定时器*/
const timer = ref(null)

onMounted(() => {
  store.updateNewMsg(false)
  if (route.query) userDetail.value = route.query
  // 清理定时器
  if (timer.value) clearInterval(timer.value)
  // 全局文件监听
  setStoreState('golbalWebcookies', 1)
  getMyCustomer()
  setTimeRresh()
  // 回显状态
  if (getStoreState('websocketEcho')) {
    headerBox.value.echoStatus()
    close()
  } else {
    open()
  }
})
/*新增消息*/
const addMessage = (content) => {
  if (messageList.value[content.fromUserKey]) {
    messageList.value[content.fromUserKey].push(content)
  } else {
    messageList.value[content.fromUserKey] = []
    messageList.value[content.fromUserKey].push(content)
  }
  setStoreState('messageList', JSON.stringify(messageList.value))
}
/*新增的客户*/
const addMyCustomer = async (content) => {
  const result = await getByKey({ sessionId: content.fromUserKey })
  let obj = {
    ...result,
    status: 1,
    avatar: listIcon.value[result.id % 10]
  }
  onlineCustomerList.value[content.fromUserKey] = obj
  addMessage(content)
  moveKeyToFront(content.fromUserKey)
}
const setTimeRresh = () => {
  timer.value = setInterval(() => {
    getMyCustomer()
  }, 60e3)
}
/*无限滚动*/
const loadScroll = () => {
  limit.value.pageNo += 1
  getMyCustomer()
}
/*获取我的客户列表*/
const getMyCustomer = async () => {
  const { list } = await getCustomerPage({ ...limit.value })
  if (list.length) {
    let obj = {}
    list.forEach((element) => {
      element.avatar = listIcon.value[element.id % 10]
      obj[element.sessionId] = element
    })
    onlineCustomerList.value = { ...onlineCustomerList.value, ...obj }
    storeMessage()
  } else {
    limit.value.pageNo -= 1
  }
}
const storeMessage = async () => {
  const messages = JSON.parse(getStoreState('messageList')) || {}
  if (Object.keys(messages).length) {
    messageList.value = messages
  } else {
    for (const key in onlineCustomerList.value) {
      let result = await getChatMessage({
        customerId: onlineCustomerList.value[key].id
      })
      result.forEach((element) => {
        if (element.userType == 1) {
          element.type = 'you'
          element.content = element.msgContent
        } else {
          element.text = element.msgContent
          element.type = 'me'
        }
        element.time = formatDates(element.createTime)
      })
      messageList.value[key] = result
    }
    setStoreState('messageList', JSON.stringify(messageList.value))
  }
}
onBeforeUnmount(() => {
  setStoreState('golbalWebcookies', '')
  if (timer.value) clearInterval(timer.value)
})
const offLine = () => {
  // 1.1 先 JSON 化 message 消息内容
  const messageContent = JSON.stringify({
    text: '',
    toUserId: 0,
    messageType: 2
  })
  // 1.2 再 JSON 化整个消息
  const jsonMessage = JSON.stringify({
    type: 'service-chat-message-send',
    content: messageContent
  })
  // 2. 最后发送消息
  send(jsonMessage)
  close()
  for (const key in onlineCustomerList.value) {
    onlineCustomerList.value[key].status = 0
  }
}
/*操作websocke打开关闭/在线离线*/
const setWebSocketStatus = (value) => {
  if (value) {
    open()
    setStoreState('websocketEcho', '')
  } else {
    offLine()
    setStoreState('websocketEcho', 'off')
  }
}
// 清除缓存
const clearStoreTarget = (key, value) => {
  if (value) {
    for (const keys in messageList.value) {
      messageList.value[keys] = []
    }
  } else {
    messageList.value[key] = []
  }
  setStoreState('messageList', JSON.stringify(messageList.value))
}
/*设置缓存*/
const setStoreState = (name, value) => {
  localStorage.setItem(name, value)
}
/*获取缓存*/
const getStoreState = (name) => {
  return localStorage.getItem(name)
}
/*选中聊天列表*/
const selectChat = (value) => {
  messageList.value[value.sessionId].forEach((element) => {
    element.reading = false
  })
  changeSessionId.value = value.sessionId
  setStoreState('messageList', JSON.stringify(messageList.value))
  chatMap.value = value
  chatDom.value.scrollDom()
  chatRight.value.cancal()
}
/*客服发消息*/
const customerSendMessage = (value, id) => {
  const messageContent = JSON.stringify({
    text: value.text,
    toUserId: id,
    messageType: 3
  })
  const jsonMessage = JSON.stringify({
    type: 'service-chat-message-send',
    content: messageContent
  })
  send(jsonMessage)
  addMessage(value)
}
/*刷新客户资料*/
const reshCustomers = (val) => {
  onlineCustomerList.value[val.sessionId] = val
  chatMap.value = val
}
/*对象排序*/
const moveKeyToFront = (key) => {
  const specialKey = key
  const myObject = onlineCustomerList.value
  const keys = Object.keys(myObject)
  const specialIndex = keys.indexOf(specialKey)
  // 如果属性已经在第一位，则不需要重排
  if (specialIndex === 0) {
    return
  }
  // 删除并重新插入特定的键到第一位
  keys.splice(specialIndex, 1)
  keys.unshift(specialKey)
  // 根据键数组构造一个新对象
  const sortedObject = {}
  keys.forEach((key) => {
    sortedObject[key] = myObject[key]
  })
  onlineCustomerList.value = sortedObject
}
/*转crm之后更新数据*/
const crmUpdate = (key) => {
  onlineCustomerList.value[key].transformed = true
}
</script>

<style lang="scss" scoped>
.wrokbench-box {
  word-break: break-word;
  height: calc(
    100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-content-padding) - var(
        --app-content-padding
      ) - var(--app-footer-height)
  );
  .wrokbench-content {
    height: calc(100% - 66px);
    display: flex;
    align-items: flex-start;
  }
}
</style>
